package org.example.service;

import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.example.Utils.PageUtils;
import org.example.entity.PageInput;
import org.example.entity.Todo;
import org.example.exceptionHandler.TodoException;
import org.example.repository.TodoRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import static org.example.Utils.Status.*;
import static org.example.exceptionHandler.errorCode.CONTENT_EXITED;
import static org.springframework.util.DigestUtils.md5DigestAsHex;

@Service
@Slf4j
@Setter(onMethod_ = @Autowired)
public class TodoService {

    private TodoRepository todoRepository;
    private JdbcTemplate template;

    public boolean addTodo(String content) {
        log.info("addTodo start....");
        String md5 = md5DigestAsHex(content.getBytes());
        List<Todo> todoList = todoRepository.findByContentMd5(md5);
        Optional<Todo> first = todoList.stream().filter(todo -> todo.getContent().equals(content)).findFirst();
        if (first.isPresent()) {
            throw new TodoException("content已存在!", CONTENT_EXITED);
        }
        log.info("addTodo end....");
        return ObjectUtils.isNotEmpty(todoRepository.save(new Todo()
                .setContent(content)
                .setStatus(ACTIVE)
                .setDeleted(NOT_DELETE)
                .setContentMd5(md5)
        ));
    }

    public org.example.entity.Page findByStatus(String status, int deleted, String keyWord, PageInput input) {
        PageRequest pageRequest = PageRequest.of(input.getPage(), input.getSize());
        Specification<Todo> specification = (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            if (status != null) {
                predicates.add(criteriaBuilder.equal(root.get("status"), status));
            }
            if (keyWord != null) {
                predicates.add(criteriaBuilder.like(root.get("content"), '%' + keyWord + '%'));
            }
            predicates.add(criteriaBuilder.equal(root.get("deleted"), deleted));

            Predicate[] p = new Predicate[predicates.size()];
            query.where(criteriaBuilder.and(predicates.toArray(p)));
            query.orderBy(criteriaBuilder.desc(root.get("createTime")));
            return query.getRestriction();
        };
        Page<Todo> all = todoRepository.findAll(specification, pageRequest);
        return new org.example.entity.Page()
                .setPageInfo(PageUtils.convertPage(all))
                .setContent(all.getContent());
    }

    public boolean deleteTodo(int id) {
        return todoRepository.deleteTodo(id) >= 1;
    }


    public boolean modifyTodoStatus(int id, String status) {
        return todoRepository.updateStatus(id, status) == 1;
    }

    public int removeCompleted() {
        return todoRepository.deleteComplete();
    }

    public List<Todo> findByDeleted() {
        return todoRepository.findByDeleted(DELETED);
    }

}
